package com.yuandian.business.monitor.service.impl;

import cn.hutool.core.date.DateUtil;
import com.yuandian.api.business_monitor.po.BusinessContrastiveAnalysisParams;
import com.yuandian.api.business_monitor.po.QueryConditionParams;
import com.yuandian.api.business_monitor.po.ShardResult;
import com.yuandian.api.business_monitor.vo.BusinessChartResVo;
import com.yuandian.api.business_monitor.vo.BusinessChartVo;
import com.yuandian.api.business_monitor.vo.BusinessMonitorVo;
import com.yuandian.api.business_monitor.vo.BusinessResVo;
import com.yuandian.base.service.ITaskDataService;
import com.yuandian.bpm.common.core.util.R;
import com.yuandian.business.monitor.mapper.BusinessContrastiveAnalysisMapper;
import com.yuandian.business.monitor.service.IBusinessComparativeAnalysisService;
import com.yuandian.business.monitor.service.ITableConfigHelpService;
import com.yuandian.utils.StringUtils;
import com.yuandian.utils.YDateUtil;
import com.yuandian.vo.TrendDataVo;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 说明：业务对比分析服务类（迁自2.5）
 *
 * @Author LinShiHe
 * @Date 2021-06-02
 */
@Slf4j
@Service
public class BusinessComparativeAnalysisImpl implements IBusinessComparativeAnalysisService {

    private static final Logger logger = LoggerFactory.getLogger(BusinessComparativeAnalysisImpl.class);

	private static final String TABLE_NAME = "ads_business_detail_stat_m";

	private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

	@Autowired
    private ITableConfigHelpService tableConfigService;

    @Autowired
    private ITaskDataService taskDataService;

    @Autowired
    private BusinessContrastiveAnalysisMapper businessContrastiveAnalysisMapper;

    /**
     * 查询性能指标列表数据
     * @param condition 请求参数
     * @return 结果集
     */
    @Override
    public R<Object> getPropertyIndex(QueryConditionParams condition) {
		BusinessResVo businessResVO = new BusinessResVo();
		ShardResult table = new  ShardResult();
		table.setTable(TABLE_NAME);

        List<Map<String, String>> maplist = new ArrayList<>();
        List<Map<String, String>> yeallist = new ArrayList<>();
        List<Map<String, String>> chainlist = new ArrayList<>();

        List<BusinessContrastiveAnalysisParams> list = new ArrayList<>();
		//  判断是否进行对比 	1-代表有进行对比, 否则进行 基值 环比 同比 的比较
		boolean hasComparison = "1".equals(condition.getId());

//=======================================================================================================================

        // 查询 基值 或者 业务一 数据
		if (hasComparison) {
			Map<String, String> map = new HashMap<>();
			map.put("tableName", TABLE_NAME);
			map.put("startTime", condition.getStartTime());
			map.put("endTime", condition.getEndTime());
			maplist.add(map);

		} else {
			// 获取表名 和 更新查询的startTime、endTime
			getTableNameAndUpdateTime(maplist, condition, table);
			// 给前端返回 当前 日期
			businessResVO.setCurrentTime(YDateUtil.yyyy_mm_dd(condition.getStartTime()));
		}

		condition.setQuerySystemId(condition.getSystemCode());
		condition.setQueryBusinessCode(condition.getBusinessCode());

		// 查询数据
		BusinessMonitorVo bm = businessContrastiveAnalysisMapper.overViewGrid(condition, maplist);

//======================================================================================================================

        // 查询环比或者业务二的数据

		if (hasComparison) {
			condition.setQuerySystemId(condition.getSystemCodes());
			condition.setQueryBusinessCode(condition.getBusinessCodes());

			if (StringUtils.isNotBlank(condition.getStartTimes()) && StringUtils.isNotBlank(condition.getEndTimes())) {
				Map<String, String> map = new HashMap<>();
				map.put("tableName", TABLE_NAME);
				map.put("startTime", condition.getStartTimes());
				map.put("endTime", condition.getEndTimes());
				yeallist.add(map);
			}
		} else {
			// 获取昨天(环比) 的日期
			getCalendarTime(condition, 1);
			condition.setQuerySystemId(condition.getSystemCode());
			condition.setQueryBusinessCode(condition.getBusinessCode());
			// 获取表名 和 更新查询的startTime、endTime
			getTableNameAndUpdateTime(yeallist, condition, table);

			// 给前端返回 环比 日期
			businessResVO.setYesterDay(YDateUtil.yyyy_mm_dd(condition.getStartTime()));
		}

		// 查询数据
		BusinessMonitorVo yeal = businessContrastiveAnalysisMapper.overViewGrid(condition, yeallist);

//=====================================================================================================================================

        // 查询 同比 或者 业务三 的数据
		if (hasComparison) {
			condition.setQuerySystemId(condition.getSystemCodess());
			condition.setQueryBusinessCode(condition.getBusinessCodess());
			if (StringUtils.isNotBlank(condition.getStartTimess()) && StringUtils.isNotBlank(condition.getEndTimess())) {
				Map<String, String> map = new HashMap<>();
				map.put("tableName", TABLE_NAME);
				map.put("startTime", condition.getStartTimess());
				map.put("endTime", condition.getEndTimess());
				chainlist.add(map);
			}
		} else {
			//  求上个月今天的日期
			getCalendarTime(condition, 2);
			condition.setQuerySystemId(condition.getSystemCode());
			condition.setQueryBusinessCode(condition.getBusinessCode());

			// 获取表名 和 更新查询的startTime、endTime
			getTableNameAndUpdateTime(chainlist, condition, table);

			// 给前端返回 同比 日期
			businessResVO.setLastMonth(YDateUtil.yyyy_mm_dd(condition.getStartTime()));
		}
		BusinessMonitorVo chain = new BusinessMonitorVo();
		// 查询数据
		if(!CollectionUtils.isEmpty(chainlist)) {
			chain = businessContrastiveAnalysisMapper.overViewGrid(condition, chainlist);
		}


		// 组装结果集
		if (ObjectUtils.isEmpty(bm)) { bm = new BusinessMonitorVo(); }
		if (ObjectUtils.isEmpty(yeal)) { yeal = new BusinessMonitorVo(); }

        BusinessContrastiveAnalysisParams contrastive = new BusinessContrastiveAnalysisParams();
        BusinessContrastiveAnalysisParams contrastive2 = new BusinessContrastiveAnalysisParams();
        BusinessContrastiveAnalysisParams contrastive3 = new BusinessContrastiveAnalysisParams();
        BusinessContrastiveAnalysisParams contrastive4 = new BusinessContrastiveAnalysisParams();
        BusinessContrastiveAnalysisParams contrastive5 = new BusinessContrastiveAnalysisParams();
        BusinessContrastiveAnalysisParams contrastive6 = new BusinessContrastiveAnalysisParams();
        BusinessContrastiveAnalysisParams contrastive7 = new BusinessContrastiveAnalysisParams();
        BusinessContrastiveAnalysisParams contrastive8 = new BusinessContrastiveAnalysisParams();
        BusinessContrastiveAnalysisParams contrastive9 = new BusinessContrastiveAnalysisParams();

        contrastive.setYeal(yeal.getVisitCount() != null ? yeal.getVisitCount().doubleValue() : 0);
        contrastive2.setYeal(yeal.getDealCount() != null ? yeal.getDealCount().doubleValue() : 0);
        contrastive3.setYeal(yeal.getAvgDealTime() != null ? yeal.getAvgDealTime() : 0);
        contrastive4.setYeal(yeal.getAverageNetTime() != null ? yeal.getAverageNetTime() : 0);
        contrastive5.setYeal(yeal.getServerAverageResponseTime() != null ? yeal.getServerAverageResponseTime() : 0);
        contrastive6.setYeal(yeal.getAlarmCount() != null ? yeal.getAlarmCount().doubleValue() : 0);
        contrastive7.setYeal(yeal.getFailCount() != null ? yeal.getFailCount().doubleValue() : 0);
        contrastive8.setYeal(yeal.getHealthRate() != null ? (double) Math.round(yeal.getHealthRate().doubleValue()*100) / 100 : 0);
        contrastive9.setYeal(yeal.getSuccessRate() != null ? (double) Math.round(yeal.getSuccessRate()*100) / 100 : 0);

        contrastive.setChain(chain.getVisitCount() != null ? chain.getVisitCount().doubleValue() : 0);
        contrastive2.setChain(chain.getDealCount() != null ? chain.getDealCount().doubleValue() : 0);
        contrastive3.setChain(chain.getAvgDealTime() != null ? chain.getAvgDealTime() : 0);
        contrastive4.setChain(chain.getAverageNetTime() != null ? chain.getAverageNetTime() : 0);
        contrastive5.setChain(chain.getServerAverageResponseTime() != null ? chain.getServerAverageResponseTime() : 0);
        contrastive6.setChain(chain.getAlarmCount() != null ? chain.getAlarmCount().doubleValue() : 0);
        contrastive7.setChain(chain.getFailCount() != null ? chain.getFailCount().doubleValue() : 0);
        contrastive8.setChain(chain.getHealthRate() != null ? (double) Math.round(chain.getHealthRate().doubleValue()*100) / 100 : 0);
        contrastive9.setChain(chain.getSuccessRate() != null ? (double) Math.round(chain.getSuccessRate()*100) / 100 : 0);

        contrastive.setMerit("访问量");
        contrastive.setBasic(bm.getVisitCount() != null ? bm.getVisitCount().doubleValue() : 0);
        list.add(contrastive);
        contrastive2.setMerit("交易量");
        contrastive2.setBasic(bm.getDealCount() != null ? bm.getDealCount().doubleValue() : 0);
        list.add(contrastive2);
        contrastive3.setMerit("平均办理时长");
        contrastive3.setBasic(bm.getAvgDealTime() != null ? bm.getAvgDealTime() : 0);
        list.add(contrastive3);
        contrastive4.setMerit("平均网络传输耗时");
        contrastive4.setBasic(bm.getAverageNetTime() != null ? bm.getAverageNetTime() : 0);
        list.add(contrastive4);
        contrastive5.setMerit("平均服务端耗时");
        contrastive5.setBasic(bm.getServerAverageResponseTime() != null ? bm.getServerAverageResponseTime() : 0);
        list.add(contrastive5);
        contrastive6.setMerit("告警数");
        contrastive6.setBasic(bm.getAlarmCount() != null ? bm.getAlarmCount().doubleValue() : 0);
        list.add(contrastive6);
        contrastive7.setMerit("失败数");
        contrastive7.setBasic(bm.getFailCount() != null ? bm.getFailCount().doubleValue() : 0);
        list.add(contrastive7);
        contrastive8.setMerit("健康度");
        contrastive8.setBasic(bm.getHealthRate() != null ? (double) Math.round(bm.getHealthRate().doubleValue()*100) / 100 : 0);
        list.add(contrastive8);
        contrastive9.setMerit("成功率");
        contrastive9.setBasic(bm.getSuccessRate() != null ? (double) Math.round(bm.getSuccessRate()*100) / 100 : 0);
        list.add(contrastive9);

        businessResVO.setList(list);
        return R.ok(businessResVO);
    }


	/**
	 *  获取表名 和 更新查询的startTime、endTime
	 * @param list	结果集
	 * @param condition	参数
	 * @param table 表对象
	 */
	private void getTableNameAndUpdateTime(List<Map<String, String>> list,
										   QueryConditionParams condition,
										   ShardResult table) {

		String start = condition.getStartTime();
		String end = condition.getEndTime();
		table.setStartTime(LocalDateTime.parse(start, FORMATTER));
		table.setEndTime(LocalDateTime.parse(end, FORMATTER));
		tableConfigService.getBpmTableMapDay(list, table);
	}


	/**
     * 查询业务对比分析的图表数据
     * @param condition 请求参数
     * @return 结果集
     */
    @Override
    public R<Object> getContrastiveCharts(QueryConditionParams condition) {
        // 记录开始和结束时间，以便后面计算X 轴
        String sTime = condition.getStartTime();
        String eTime = condition.getEndTime();

		//  判断是否进行对比 	1-代表有进行对比, 否则进行 基值 环比 同比 的比较
		boolean hasComparison = "1".equals(condition.getId());

        // 进行相同业务不同时间对比
        if (condition.getComparativeType() != null && condition.getComparativeType() == 1 && hasComparison) {
            if (StringUtils.isNotEmpty(condition.getEndTime())
                    && !"00:00".equals(condition.getEndTime().substring(11, 16))) {
                condition.setNowTime(condition.getEndTime());
                condition.setLowVal(1);
                condition.setEndTime(YDateUtil.getAfterDay(condition.getEndTime()));
                sTime = condition.getStartTime();
                eTime = condition.getEndTime();
            }

            if (StringUtils.isNotEmpty(condition.getEndTimes())
                    && !"00:00".equals(condition.getEndTimes().substring(11, 16))) {
                condition.setNowTime(condition.getEndTimes());
                condition.setLowVal(2);
                condition.setEndTimes(YDateUtil.getAfterDay(condition.getEndTimes()));
                sTime = condition.getStartTimes();
                eTime = condition.getEndTimes();
            }

            if (StringUtils.isNotEmpty(condition.getEndTimess())
                    && !"00:00".equals(condition.getEndTimess().substring(11, 16))) {
                condition.setNowTime(condition.getEndTimess());
                condition.setLowVal(3);
                condition.setEndTimess(YDateUtil.getAfterDay(condition.getEndTimess()));
                sTime = condition.getStartTimess();
                eTime = condition.getEndTimess();
            }
        }

        BusinessChartResVo res = new BusinessChartResVo();
        // 用于保存表名
        List<Map<String, String>> maplist = new ArrayList<>();     // 当前值
        List<Map<String, String>> yeallist = new ArrayList<>();   // 环比
        List<Map<String, String>> chainlist = new ArrayList<>(); // 同比

        // 保存结果集
        List<BusinessMonitorVo> list = new ArrayList<>();        // 当前值
        List<BusinessMonitorVo> list2 = new ArrayList<>();      // 环比
        List<BusinessMonitorVo> list3 = new ArrayList<>();     // 同比

		String tableNameType = "m";
        ShardResult table = new ShardResult();
        table.setTable(TABLE_NAME);

        tableNameType = table.getType();

         try {
			//  判断是否进行对比 1.代表有进行对比
            if (hasComparison) {
                Map<String, String> map = new HashMap<>();
                map.put("tableName", TABLE_NAME);
                map.put("startTime", condition.getStartTime());
                map.put("endTime", condition.getEndTime());
                maplist.add(map);
                // 获取表名
                condition.setQuerySystemId(condition.getSystemCode());
                condition.setQueryBusinessCode(condition.getBusinessCode());
            } else {
                // 根据表类型提升开始和结束时间
                String start = condition.getStartTime();
                String end = condition.getEndTime();
                table.setStartTime(LocalDateTime.parse(start, FORMATTER));
                table.setEndTime(LocalDateTime.parse(end, FORMATTER));

                tableConfigService.getBpmTableMapDay(maplist, table);

                condition.setQuerySystemId(condition.getSystemCode());
                condition.setQueryBusinessCode(condition.getBusinessCode());
            }


        } catch (Exception e) {
            e.printStackTrace();
            logger.error("业务对比分析now表生成报错");
        }
        logger.info("业务对比分析当前值或者业务1表趋势生成:" + maplist);
        if(maplist.size() > 0) {

            list = businessContrastiveAnalysisMapper.overViewAnalysis(condition, maplist);
        }

        try {
			//  判断是否进行对比 1.代表有进行对比
            if (hasComparison) {
                Map<String, String> map = new HashMap<>();
                map.put("tableName", TABLE_NAME);
                map.put("startTime", condition.getStartTimes());
                map.put("endTime", condition.getEndTimes());
                yeallist.add(map);
                condition.setQuerySystemId(condition.getSystemCodes());
                condition.setQueryBusinessCode(condition.getBusinessCodes());
            } else {
                getCalendarTime(condition, 1);
                // 根据表类型提升开始和结束时间
                String start = condition.getStartTime();
                String end = condition.getEndTime();
                table.setStartTime(LocalDateTime.parse(start, FORMATTER));
                table.setEndTime(LocalDateTime.parse(end, FORMATTER));

                tableConfigService.getBpmTableMapDay(yeallist, table);

                condition.setQuerySystemId(condition.getSystemCode());
                condition.setQueryBusinessCode(condition.getBusinessCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        }
        logger.info("业务对比分析环比或者业务2表趋势生成:" + yeallist);
        if(yeallist.size() > 0) {
            // 执行查询
            list2 = businessContrastiveAnalysisMapper.overViewAnalysis(condition, yeallist);
        }

        try {
			//  判断是否进行对比 1.代表有进行对比
            if (hasComparison) {
                Map<String, String> map = new HashMap<>();
                map.put("tableName", TABLE_NAME);
                map.put("startTime", condition.getStartTimess());
                map.put("endTime", condition.getEndTimess());
                chainlist.add(map);
                condition.setQuerySystemId(condition.getSystemCodess());
                condition.setQueryBusinessCode(condition.getBusinessCodess());
            } else {
				getCalendarTime(condition, 2);
				// 根据表类型提升开始和结束时间
                String start = condition.getStartTime();
                String end = condition.getEndTime();
                table.setStartTime(LocalDateTime.parse(start, FORMATTER));
                table.setEndTime(LocalDateTime.parse(end, FORMATTER));

				tableConfigService.getBpmTableMapDay(chainlist, table);

                condition.setQuerySystemId(condition.getSystemCode());
                condition.setQueryBusinessCode(condition.getBusinessCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        }
        logger.info("业务对比分析同比或者业务3表趋势生成:" + chainlist);
        if(chainlist.size() > 0) {
            // 执行查询
            list3 = businessContrastiveAnalysisMapper.overViewAnalysis(condition, chainlist);
        }

        if (maplist.size() > 0 && StringUtils.isEmpty(tableNameType)) {
            tableNameType = maplist.get(0).get("tableName").split("_")[4];
        }

        if (hasComparison) {
            try {
                logger.info("根据SQL查询出来的数据针对折线图进行进一步封装。。。");
                long startTime1 = System.currentTimeMillis();
                /**
                 * 将任务的任务名称、查询的开始时间、查询的结束时间，趋势图数组或者对象传到此方法里，此方法会计算趋势图的开始时间、结束时间，
                 * 并返回一个包装类，不会对趋势图数组或者对象进行加工
                 */
                TrendDataVo trendDataVo = new TrendDataVo();
                if ("m".equals(tableNameType)){
                    trendDataVo=taskDataService.getTrendObject("详单表分钟统计",sTime,eTime,null);
                    if (trendDataVo.isLastShow()){
                        eTime= trendDataVo.trendEndTime;
                    }else{
                        eTime= YDateUtil.parseDateToStr(YDateUtil.YYYY_MM_DD_HH_MM_SS,new Date(DateUtil.parse(eTime,YDateUtil.YYYY_MM_DD_HH_MM_SS).getTime()-60*1000));
                    }
                }else{
                    trendDataVo=taskDataService.getTrendObject("业务小时统计",sTime,eTime,null);
                }
                res = getResult(list, list2, list3,sTime,eTime, condition,trendDataVo.isLastShow());


                long endTime1 = System.currentTimeMillis();
                logger.info("数据封装完毕，总耗时： " + (endTime1 - startTime1) + "ms" );
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {

            try {
                logger.info("根据SQL查询出来的数据进行对折线图数据进行进一步封装。。。");
                long startTime1 = System.currentTimeMillis();
                TrendDataVo trendDataVo=new TrendDataVo();
                if ("m".equals(tableNameType)){
                     trendDataVo=taskDataService.getTrendObject("详单表分钟统计",sTime,eTime,null);
                    if (trendDataVo.isLastShow()){
                        eTime= trendDataVo.trendEndTime;
                    }else{
                        eTime= YDateUtil.parseDateToStr(YDateUtil.YYYY_MM_DD_HH_MM_SS,new Date(DateUtil.parse(eTime,YDateUtil.YYYY_MM_DD_HH_MM_SS).getTime()-60*1000));
                    }
                }else{
                    trendDataVo=taskDataService.getTrendObject("业务小时统计",sTime,eTime,null);
                }
                res = getResult(list, list2, list3,sTime,eTime, condition,trendDataVo.isLastShow());
                long endTime1 = System.currentTimeMillis();
                logger.info("数据封装完毕，总耗时： " + (endTime1 - startTime1) + "ms" );
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        return R.ok(res);
    }


    /**
     * 求出 今天 昨天 上个月的这一天
     * @param condition 请求参数
     * @param a
	 */
    public static void getCalendarTime(QueryConditionParams condition, int a) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime startTimeL = LocalDateTime.parse(condition.getStartTime(), formatter);
        LocalDateTime endTimeL = LocalDateTime.parse(condition.getEndTime(), formatter);
        LocalDateTime startDateTime = null;
        LocalDateTime endDateTime = null;

        if (a == 1) {

            startDateTime = startTimeL.minusDays(1);
            endDateTime = endTimeL.minusDays(1);

        } else {
            // 这里加一天是环比减了一天
            startDateTime = startTimeL.minusMonths(1L).plusDays(1L);
            endDateTime = endTimeL.minusMonths(1L).plusDays(1L);
        }

        condition.setStartTime(startDateTime.format(formatter));
        condition.setEndTime(endDateTime.format(formatter));
	}


    private static BusinessChartResVo getResult(List<BusinessMonitorVo> list, List<BusinessMonitorVo> list2,
												List<BusinessMonitorVo> list3, String sTime, String eTime, QueryConditionParams condition, Boolean lastShow) throws ParseException {

        // 获取开始时间和结束时间的差值
        long minutes = YDateUtil.timeDistance(sTime, eTime);

        // 获取X轴相邻刻度的间隔
        int timeInterval = getTimeInterval(minutes);
        LinkedHashMap<String, BusinessChartVo> map = new LinkedHashMap<>();
        // 将结果集聚合到各个时间段(也就是折线的 X轴)
        List<String> timeList = getTimeList(sTime, eTime, timeInterval);

        for(int i = 0; i < timeList.size(); i++) {
            map.put(timeList.get(i).substring(11, 16), new BusinessChartVo());
        }


        BusinessChartVo businessChartVO = new BusinessChartVo();

        // 基值 或 业务一 的值
        for (int i = 0; i < list.size(); i++) {
            // 根据cycleTime计算归属区间
            String cycleTimeS = getTimeKey(list.get(i).getCycleTime(), timeInterval);
            BusinessChartVo busiChartVO = map.get(cycleTimeS);

            if (busiChartVO != null) {
                busiChartVO.setAlarmCount1(busiChartVO.getAlarmCount1() == null ? list.get(i).getAlarmCount() : (busiChartVO.getAlarmCount1() + list.get(i).getAlarmCount()));
                busiChartVO.setDealCount1(busiChartVO.getDealCount1() == null ? list.get(i).getDealCount() : (busiChartVO.getDealCount1() + list.get(i).getDealCount()));
                busiChartVO.setSuccessCount1(busiChartVO.getSuccessCount1() == null ? list.get(i).getVisitCount() : (busiChartVO.getSuccessCount1() + list.get(i).getVisitCount()));
                busiChartVO.setAvgDealTime1(busiChartVO.getAvgDealTime1() == null ? list.get(i).getTotalDealTime() : (busiChartVO.getAvgDealTime1() + list.get(i).getTotalDealTime()));
                busiChartVO.setServerAverageResponseTime1(busiChartVO.getServerAverageResponseTime1() == null ? list.get(i).getTotalServerResponseTime() : (busiChartVO.getServerAverageResponseTime1() + list.get(i).getTotalServerResponseTime()));
                // 记录每个刻度聚合的数据量，用于求平均
                busiChartVO.setResNum1(busiChartVO.getResNum1() + 1);
            }
        }

        // 环比 或 业务二 的值
        for (int i = 0; i < list2.size(); i++) {
            // 根据cycleTime计算归属区间
            String cycleTimeS = getTimeKey(list2.get(i).getCycleTime(), timeInterval);
            BusinessChartVo busiChartVO = map.get(cycleTimeS);

            if (busiChartVO != null) {
                busiChartVO.setAlarmCount2(busiChartVO.getAlarmCount2() == null ? list2.get(i).getAlarmCount() : (busiChartVO.getAlarmCount2() + list2.get(i).getAlarmCount()));
                busiChartVO.setDealCount2(busiChartVO.getDealCount2() == null ? list2.get(i).getDealCount() : (busiChartVO.getDealCount2() + list2.get(i).getDealCount()));
                busiChartVO.setSuccessCount2(busiChartVO.getSuccessCount2() == null ? list2.get(i).getVisitCount() : (busiChartVO.getSuccessCount2() + list2.get(i).getVisitCount()));
                busiChartVO.setAvgDealTime2(busiChartVO.getAvgDealTime2() == null ? list2.get(i).getTotalDealTime() : (busiChartVO.getAvgDealTime2() + list2.get(i).getTotalDealTime()));
                busiChartVO.setServerAverageResponseTime2(busiChartVO.getServerAverageResponseTime2() == null ? list2.get(i).getTotalServerResponseTime() : (busiChartVO.getServerAverageResponseTime2() + list2.get(i).getTotalServerResponseTime()));

                busiChartVO.setResNum2(busiChartVO.getResNum2() + 1);
            }
        }

        // 同比 或 业务三 的值
        for (int i = 0; i < list3.size(); i++) {
            // 根据cycleTime计算归属区间
            String cycleTimeS = getTimeKey(list3.get(i).getCycleTime(), timeInterval);
            BusinessChartVo busiChartVO = map.get(cycleTimeS);

            if (busiChartVO != null) {
                busiChartVO.setAlarmCount3(busiChartVO.getAlarmCount3() == null ? list3.get(i).getAlarmCount() : (busiChartVO.getAlarmCount3() + list3.get(i).getAlarmCount()));
                busiChartVO.setDealCount3(busiChartVO.getDealCount3() == null ? list3.get(i).getDealCount() : (busiChartVO.getDealCount3() + list3.get(i).getDealCount()));
                busiChartVO.setSuccessCount3(busiChartVO.getSuccessCount3() == null ? list3.get(i).getVisitCount() : (busiChartVO.getSuccessCount3() + list3.get(i).getVisitCount()));
                busiChartVO.setAvgDealTime3(busiChartVO.getAvgDealTime3() == null ? list3.get(i).getTotalDealTime() : (busiChartVO.getAvgDealTime3() + list3.get(i).getTotalDealTime()));
                busiChartVO.setServerAverageResponseTime3(busiChartVO.getServerAverageResponseTime3() == null ? list3.get(i).getTotalServerResponseTime() : (busiChartVO.getServerAverageResponseTime3() + list3.get(i).getTotalServerResponseTime()));

                busiChartVO.setResNum3(busiChartVO.getResNum3() + 1);
            }
        }

        List<Long> dealList1 = new ArrayList<>();
        List<Double> avgDealTimeList1 = new ArrayList<>();
        List<Double> serverAverageResponseList1 = new ArrayList<>();
        List<Double> healthList1 = new ArrayList<>();

        List<Long> dealList2 = new ArrayList<>();
        List<Double> avgDealTimeList2 = new ArrayList<>();
        List<Double> serverAverageResponseList2 = new ArrayList<>();
        List<Double> healthList2 = new ArrayList<>();

        List<Long> dealList3 = new ArrayList<>();
        List<Double> avgDealTimeList3 = new ArrayList<>();
        List<Double> serverAverageResponseList3 = new ArrayList<>();
        List<Double> healthList3 = new ArrayList<>();

        Iterator<Map.Entry<String, BusinessChartVo>> it = map.entrySet().iterator();
        // 封装结果集
        while (it.hasNext()) {
            businessChartVO = (BusinessChartVo) it.next().getValue();

            // 除以resNum是用于求平均值
            dealList1.add((long)Math.floor((businessChartVO.getDealCount1() == null ? 0 : businessChartVO.getDealCount1())));
            avgDealTimeList1.add((double)Math.round((businessChartVO.getAvgDealTime1() == null ? 0 : businessChartVO.getAvgDealTime1()) / (businessChartVO.getSuccessCount1() == null ? 1 : businessChartVO.getSuccessCount1()) * 100) / 100);
            serverAverageResponseList1.add((double)Math.round((businessChartVO.getServerAverageResponseTime1() == null ? 0 : businessChartVO.getServerAverageResponseTime1()) / (businessChartVO.getSuccessCount1() == null ? 1 : businessChartVO.getSuccessCount1()) * 100) / 100);

            healthList1.add(businessChartVO.getSuccessCount1() == null  ? 0 : ((businessChartVO.getSuccessCount1() != null && businessChartVO.getAlarmCount1() == null) ? 1 :
                    (double)getHealth(businessChartVO.getSuccessCount1(), businessChartVO.getAlarmCount1())));

            dealList2.add((long)Math.floor((businessChartVO.getDealCount2() == null ? 0 : businessChartVO.getDealCount2())));
            avgDealTimeList2.add((double)Math.round((businessChartVO.getAvgDealTime2() == null ? 0 : businessChartVO.getAvgDealTime2()) / (businessChartVO.getSuccessCount2() == null ? 1 : businessChartVO.getSuccessCount2()) * 100) / 100);
            serverAverageResponseList2.add((double)Math.round((businessChartVO.getServerAverageResponseTime2() == null ? 0 : businessChartVO.getServerAverageResponseTime2()) / (businessChartVO.getSuccessCount2() == null ? 1 : businessChartVO.getSuccessCount2()) * 100) / 100);

            healthList2.add(businessChartVO.getSuccessCount2() == null  ? 0 : ((businessChartVO.getSuccessCount2() != null && businessChartVO.getAlarmCount2() == null) ? 1 :
                    (double)getHealth(businessChartVO.getSuccessCount2(), businessChartVO.getAlarmCount2())));

            dealList3.add((long)Math.floor((businessChartVO.getDealCount3() == null ? 0 : businessChartVO.getDealCount3())));
            avgDealTimeList3.add((double)Math.round((businessChartVO.getAvgDealTime3() == null ? 0 : businessChartVO.getAvgDealTime3()) /  (businessChartVO.getSuccessCount3() == null ? 1 : businessChartVO.getSuccessCount3()) * 100) / 100);
            serverAverageResponseList3.add((double)Math.round((businessChartVO.getServerAverageResponseTime3() == null ? 0 : businessChartVO.getServerAverageResponseTime3()) /  (businessChartVO.getSuccessCount3() == null ? 1 : businessChartVO.getSuccessCount3()) * 100) / 100);

            healthList3.add(businessChartVO.getSuccessCount3() == null  ? 0 : ((businessChartVO.getSuccessCount3() != null && businessChartVO.getAlarmCount3() == null) ? 1 :
                    (double)getHealth(businessChartVO.getSuccessCount3(), businessChartVO.getAlarmCount3())));
        }


        if (condition.getComparativeType() != null && condition.getComparativeType() == 1 && "1".equals(condition.getId())
                && StringUtils.isNotEmpty(condition.getNowTime())) {

            int index = -1;
            if (StringUtils.isNotEmpty(condition.getNowTime())) {
                // 判断当前时间在X轴中的下标位置
                String cycleTimeS = getTimeKey(condition.getNowTime(), timeInterval);
                for (int i = 0; i < timeList.size(); i++) {
                    if(cycleTimeS.equals(timeList.get(i).substring(11, 16))) {
                        index = i;
                        break;
                    }
                }

                // 把查询今天的数据进行置空
                if (condition.getLowVal() == 1) {
                    for (int i = index + 1; i < dealList1.size(); i++) {
                        dealList1.set(i, null);
                    }
                    for (int i = index + 1; i < avgDealTimeList1.size(); i++) {
                        avgDealTimeList1.set(i, null);
                    }
                    for (int i = index + 1; i < serverAverageResponseList1.size(); i++) {
                        serverAverageResponseList1.set(i, null);
                    }
                    for (int i = index + 1; i < healthList1.size(); i++) {
                        healthList1.set(i, null);
                    }
                }else if (condition.getLowVal() == 2) {
                    for (int i = index + 1; i < dealList2.size(); i++) {
                        dealList2.set(i, null);
                    }
                    for (int i = index + 1; i < avgDealTimeList2.size(); i++) {
                        avgDealTimeList2.set(i, null);
                    }
                    for (int i = index + 1; i < serverAverageResponseList2.size(); i++) {
                        serverAverageResponseList2.set(i, null);
                    }
                    for (int i = index + 1; i < healthList2.size(); i++) {
                        healthList2.set(i, null);
                    }
                }else if (condition.getLowVal() == 3) {
                    for (int i = index + 1; i < dealList3.size(); i++) {
                        dealList3.set(i, null);
                    }
                    for (int i = index + 1; i < avgDealTimeList3.size(); i++) {
                        avgDealTimeList3.set(i, null);
                    }
                    for (int i = index + 1; i < serverAverageResponseList3.size(); i++) {
                        serverAverageResponseList3.set(i, null);
                    }
                    for (int i = index + 1; i < healthList3.size(); i++) {
                        healthList3.set(i, null);
                    }
                }
            }
        }


        // 将 12 个list封装成四个折线图的的结果集
        List<List<Long>> dealResList = new ArrayList<>();
        List<List<Double>> avgDealTimeResList = new ArrayList<>();
        List<List<Double>> serverAverageResponseResList = new ArrayList<>();
        List<List<Double>> healthResList = new ArrayList<>();

        dealResList.add(dealList1);
        dealResList.add(dealList2);
        dealResList.add(dealList3);

        avgDealTimeResList.add(avgDealTimeList1);
        avgDealTimeResList.add(avgDealTimeList2);
        avgDealTimeResList.add(avgDealTimeList3);

        serverAverageResponseResList.add(serverAverageResponseList1);
        serverAverageResponseResList.add(serverAverageResponseList2);
        serverAverageResponseResList.add(serverAverageResponseList3);

        healthResList.add(healthList1);
        healthResList.add(healthList2);
        healthResList.add(healthList3);



        // 返回结果对象
        BusinessChartResVo businessChartResVO = new BusinessChartResVo();
        businessChartResVO.setDealResList(dealResList);
        businessChartResVO.setAvgDealTimeResList(avgDealTimeResList);
        businessChartResVO.setServerAverageResponseResList(serverAverageResponseResList);
        businessChartResVO.setHealthResList(healthResList);
        // 当x轴最后一个刻度为第二天的00：00:00 时则去掉
//        if ("00:00".equals(timeList.get(timeList.size() - 1).substring(11, 16))) {
//            timeList.remove(timeList.size() - 1);
//        }

        businessChartResVO.setXList(timeList);

        return businessChartResVO;
    }


    /**
     * 根据时间差判断时间所属刻度
     * @param time
     * @param timeInterval
     * @return 结果集
     */
    public static String getTimeKey(String time, int timeInterval) {
        int year = 0, month = 0, day = 0, hour = 0, min = 0;
        Date date = YDateUtil.yyyy_MM_dd_HH_mm(time);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        year = calendar.get(Calendar.YEAR);
        month = calendar.get(Calendar.MONTH);
        day = calendar.get(Calendar.DAY_OF_MONTH);
        hour = calendar.get(Calendar.HOUR_OF_DAY);
        // 向前归属
        min = calendar.get(Calendar.MINUTE) / timeInterval * timeInterval;
        calendar.set(year, month, day, hour, min);
        date = calendar.getTime();
        time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
        return time.substring(11, 16);
    }

    /**
     * 获取X轴相邻刻度的间隔：
     *      一个小时以内（X <= 60分钟） 则1分钟一个刻度
     *      一个小时到五小时以内（60 < X <= 300） 5分钟一个刻度
     *      五个小时到十个小时（300 < X <= 600） 10分钟一个刻度
     *      十个小时到十五个小时（600 < X <= 900) 15分钟一个刻度
     *      十五个小时到二十四个小时（900 < X <=1440） 30分钟一个刻度

     * @return 结果集
     */
    private static int getTimeInterval(long minutes) {
        int timeInterval = 1;
        if(minutes <= 60L) {
            timeInterval = 1;
        }else if(minutes <= 300L) {
            timeInterval = 5;
        }else if(minutes <= 600L) {
            timeInterval = 10;
        }else if(minutes <= 900L) {
            timeInterval = 15;
        }else if(minutes <=1440L) {
            timeInterval = 30;
        }
        return timeInterval;
    }

    /**
     * 根据开始时间、结束时间、时间间隔 自动生成X轴数据
     * @param starTime
     * @param endTime
     * @param timeInterval 时间间隔
     * @return 结果集
     */
    public static List<String> getTimeList(String starTime, String endTime, int timeInterval) {

        List<String> timeList = new ArrayList<>();
        int year = 0, month = 0, day = 0, hour = 0, min = 0;
        Date startDate = YDateUtil.yyyy_MM_dd_HH_mm(starTime);
        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(startDate);
        year = startCalendar.get(Calendar.YEAR);
        month = startCalendar.get(Calendar.MONTH);
        day = startCalendar.get(Calendar.DAY_OF_MONTH);
        hour = startCalendar.get(Calendar.HOUR_OF_DAY);
        // 向前归属
        min = startCalendar.get(Calendar.MINUTE) / timeInterval * timeInterval;
        startCalendar.set(year, month, day, hour, min);
        startDate = startCalendar.getTime();
        starTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(startDate);

        Date endDate = YDateUtil.yyyy_MM_dd_HH_mm(endTime);
        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(endDate);
        year = endCalendar.get(Calendar.YEAR);
        month = endCalendar.get(Calendar.MONTH);
        day = endCalendar.get(Calendar.DAY_OF_MONTH);
        hour = endCalendar.get(Calendar.HOUR_OF_DAY);
        // 向前归属
        min = endCalendar.get(Calendar.MINUTE) / timeInterval * timeInterval;
        endCalendar.set(year, month, day, hour, min);
        endDate = endCalendar.getTime();
        endTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(endDate);

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 把日期时间格式化
        LocalDateTime start = LocalDateTime.parse(starTime, formatter);
        LocalDateTime end = LocalDateTime.parse(endTime, formatter);

        while(!start.equals(end)) {
            timeList.add(start.toString());
            start = start.plusMinutes(timeInterval);
        }
        timeList.add(end.toString());

        return timeList;
    }

    public static Double getHealth(Long successCount, Long alarmCount) {
        return new BigDecimal((double) (successCount - alarmCount) / successCount).setScale(2, RoundingMode.HALF_UP).doubleValue();
    }

    public static void main(String[] args) {
        System.out.println(getHealth(4L, 2L));
    }

}
